package com.wl.dzt.sys.controller.action;

import com.wl.dzt.sys.controller.fileupload.FileUploadTemplate;
import com.wl.dzt.sys.controller.param.Param;
import com.wl.dzt.sys.controller.result.ActionResult;
import com.wl.dzt.sys.controller.result.FormResult;
import com.wl.dzt.sys.core.dao.DB;
import com.wl.dzt.sys.core.dao.curd.validate.Validate;
import com.wl.dzt.sys.util.FieldUtil;
import com.wl.dzt.sys.util.LogicUtil;
import com.wl.dzt.sys.util.clazz.ClassUtil;
import com.wl.dzt.sys.util.json.Json;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @author wl_code@163.com
 * @version 1.0
 * @date 2018/7/5/005
 * @description 保存动作
 * 用于处理保存请求
 * 根据参数自动识别修改或者删除
 * 支持保存验证和自定义验证
 */
@Component
public class SaveAction implements Action {

    /**
     * 文件上传模板
     */
    @Resource
    private FileUploadTemplate fileUploadTemplate;

    public ActionResult doAction(Param param) {
        ActionResult actionResult = new ActionResult();
        FormResult formResult = new FormResult();
        actionResult.setFormResult(formResult);
        HttpServletRequest request = param.getRequest();
        formResult.setSuccess(true);
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
        this.adaptation(param);
        MultipartHttpServletRequest multiRequest = null;
        if (multipartResolver.isMultipart(request)) {
            multiRequest = (MultipartHttpServletRequest) request;
            // 校验
            {
                Iterator<String> iter = multiRequest.getFileNames();
                while (iter.hasNext()) {
                    String fileName = iter.next();
                    MultipartFile file = multiRequest.getFile(fileName);
                    if (file != null && !LogicUtil.empty(file.getOriginalFilename())) {
                        if (file.getSize() > FileUploadTemplate.FILE_MAX_SIZE) {
                            formResult.putError(fileName, "文件过大,最大支持10M以内!");
                            formResult.setSuccess(false);
                            return actionResult;
                        }
                    }
                }
            }
        }

        List<Validate> vs = param.getValidates();
        List<Validate> validates = DB.saveByDetailed(param.getEntity(), vs.toArray(new Validate[vs.size()]));
        // 验证错误
        if (validates != null) {
            validates.forEach(validate -> formResult.putError(validate.getField(), validate.getError()));
            formResult.setSuccess(false);
        } else {
            if (multipartResolver.isMultipart(request)) {
                Iterator<String> iter = multiRequest.getFileNames();
                while (iter.hasNext()) {
                    String fileName = iter.next();
                    MultipartFile file = multiRequest.getFile(fileName);
                    if (!LogicUtil.empty(file.getOriginalFilename())) {
                        fileUploadTemplate.upLoad(file, param);
                    }
                }
                DB.save(param.getEntity());
            }
        }
        BeanMap beanMap = BeanMap.create(param.getEntity());
        formResult.setId(beanMap.get("id") + "");
        actionResult.setFormResult(formResult);
        return actionResult;
    }

    /**
     * <b>适配页面set</b>
     * <p>
     * 根据页面参数和实体设置,保存的时候自动组装set中的值以便级联保存。
     * </p>
     *
     * @param param
     */
    private void adaptation(Param param) {
        Object entity = param.getEntity();
        BeanMap map = BeanMap.create(entity);
        HttpServletRequest request = param.getRequest();
        for (FieldUtil.RefSetInfo info : FieldUtil.getEntitySet(entity)) {
            String json = request.getParameter(info.getSrcField());
            if (!LogicUtil.empty(json)) {
                List<Map<String, Object>> list = Json.recover(json, Json.LIST_MAP_OBJECT);
                // 可能存在数据格式不规范问题手动调用修复一次
                Json.correction(list, info.getSrcClass());
                Set<Object> set = new HashSet<>();
                list.forEach(m -> {
                    Object obj = ClassUtil.newInstance(info.getSrcClass());
                    BeanMap beanMap = BeanMap.create(obj);
                    beanMap.putAll(m);

                    // 弥补beanmap只能填充当前实体属性字段
                    {
                        m.forEach((key, val) -> {
                            if (key.contains(".")) {
                                String refField = key.split("[.]")[0];
                                try {
                                    Object ref = ClassUtil.newInstance(obj.getClass().getDeclaredField(refField).getType());
                                    DB.setId(ref, val.toString());
                                    beanMap.put(refField, ref);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }

                    beanMap.put("id", null);
                    set.add(obj);
                });
                map.put(info.getSrcField(), set);
            }
        }
    }
}
